
//#include <tchar.h>
#include "stdafx.h"

#include "filguid.h"
#include "Filter.h"
#include "pi.h"
#include "resource.h"


/*Common to All*/
#define TEST MessageBox(0,"Test","TestWindow",0)

const AMOVIESETUP_MEDIATYPE filPinTypes=
{
	&MEDIATYPE_Video,
	&MEDIASUBTYPE_NULL
};
const AMOVIESETUP_MEDIATYPE filPinTypesa=
{
	&MEDIATYPE_Audio,
	&MEDIASUBTYPE_NULL
};
const AMOVIESETUP_PIN filPinsa[]=
{
	{
		L"Input",
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		&CLSID_NULL,
		NULL,
		1,
		&filPinTypesa
	}
	,
	{
		L"Output",
		FALSE,
		TRUE,
		FALSE,
		FALSE,
		&CLSID_NULL,
		NULL,
		1,
		&filPinTypesa
	}
	

};
const AMOVIESETUP_PIN filPins[]=
{
	{
		L"Input",
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		&CLSID_NULL,
		NULL,
		1,
		&filPinTypes
	},
	{
		L"Output",
		FALSE,
		TRUE,
		FALSE,
		FALSE,
		&CLSID_NULL,
		NULL,
		1,
		&filPinTypes
	}
};
const AMOVIESETUP_FILTER filFiltera=
{
	&CLSID_AuFilter,
	L"AuFilter",
	MERIT_DO_NOT_USE,
	2,
	filPinsa
};
const AMOVIESETUP_FILTER filFilter=
{
	&CLSID_Filter,
	L"Filter",
	MERIT_DO_NOT_USE,
	2,
	filPins
};

CFactoryTemplate g_Templates[]=
{
	{
		L"Filter",
		&CLSID_Filter,
		Filter::CreateInstance,
		NULL,
		&filFilter
	},
	{
		L"AuFilter",
		&CLSID_AuFilter,
		AuFilter::CreateInstance,
		NULL,
		&filFiltera
	}
};

int g_cTemplates=sizeof(g_Templates)/sizeof(g_Templates[0]);

HINSTANCE hMod;

//
// DllEntryPoint
//
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule, 
                      DWORD  dwReason, 
                      LPVOID lpReserved)
{
	hMod = (HINSTANCE)hModule;

	return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

#ifdef __cplusplus
extern "C"{
#endif

STDAPI DllRegisterServer()
{
	return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
	return AMovieDllRegisterServer2(FALSE);
}
#ifdef __cplusplus
}
#endif

/**********************Audio Effect Starting*********************/

AuFilter::AuFilter(TCHAR *autzname,LPUNKNOWN punk,HRESULT *hr):
CTransInPlaceFilter(autzname,punk,CLSID_AuFilter,hr,TRUE)
{
	mod=NULL;
}

CUnknown* WINAPI AuFilter::CreateInstance(LPUNKNOWN punk,HRESULT*hr)
{
	AuFilter*pObject=new AuFilter(NAME("AuFilter"),punk,hr);
	if(pObject==NULL)
	{
		*hr=E_OUTOFMEMORY;
	}
	return pObject;

}

HRESULT AuFilter::NonDelegatingQueryInterface(REFIID riid,void **ppv)
{
	if(riid==IID_AuFilter)
	{
		return GetInterface((IAuFilter*)this,ppv);
	}
	else
	{
		return CTransInPlaceFilter::NonDelegatingQueryInterface(riid,ppv);
	}
}

HRESULT AuFilter::CheckInputType(const CMediaType *pmtin)
{
	WAVEFORMATEX*wfe=(WAVEFORMATEX*)pmtin->pbFormat;

	if(pmtin->majortype!=MEDIATYPE_Audio)
		return VFW_E_TYPE_NOT_ACCEPTED;

	if(pmtin->formattype!=FORMAT_WaveFormatEx)
		return VFW_E_TYPE_NOT_ACCEPTED;

	if(wfe->wFormatTag !=WAVE_FORMAT_PCM)
		return VFW_E_TYPE_NOT_ACCEPTED;
	
	if(mod)
	{
		wf=*wfe;
		mod->open(wf.wBitsPerSample,wf.nChannels,wf.nSamplesPerSec);
		
	}
	return NOERROR;
}

HRESULT AuFilter::Transform(IMediaSample *pSample)
{
    BYTE *samples;
	pSample->GetPointer(&samples);
	
	if(mod)
	{
		mod->write(samples,pSample->GetActualDataLength(),wf.wBitsPerSample,wf.nChannels,wf.nSamplesPerSec);
	}
	
	return NOERROR;
}

STDMETHODIMP AuFilter::SetDspfunction(AuSample*modt)
{
	mod=modt;
	return NOERROR;
}

STDMETHODIMP AuFilter::SetStop()
{
	if(mod)
		mod->close();
	mod=NULL;
	return NOERROR;
}

/****************End of Audio Effect**********************/


/****************Start of Image Effect********************/

Filter::Filter(TCHAR *fitzname,
			   LPUNKNOWN punk,
			   HRESULT *hr):
CTransInPlaceFilter(fitzname,punk,CLSID_Filter,hr)
//CPersistStream(punk,hr)
{
	iOption=0;
	iExtEff=0;
	iOptionSmooth=0;
	cxImage = 0;
	cyImage = 0;
	img=NULL;
}

Filter::~Filter()
{
	if(img)
	{
			img->Quit(); 
	}
	img=NULL;
	if(hmod)
	{
		FreeLibrary(hmod);
		hmod=NULL;
	}

}

STDMETHODIMP Filter::SetConfigure(HWND hwnd)
{
	if(img)
	{
		img->Configure(hwnd);
	}
	return NOERROR;
}
STDMETHODIMP Filter::SetExtEff(char *fname)
{
	if(fname!=NULL)
	{
		if(img)
		{
			img->Quit(); 
		}
		img=NULL;
		FreeLibrary(hmod);
		hmod=NULL;
		hmod=LoadLibrary(fname);
		Init=NULL;
		if(hmod != NULL)
		{
			Init=(INIT)GetProcAddress(hmod,"Getplugin");
		}
		if(Init)
		{
			img=Init();
		}
		if(img)
		{
			img->Init();
		}
		Init=NULL;
		
	
	}
	return NOERROR;
}

STDMETHODIMP Filter::SetStop()
{
	if(img)
	{
		img->Quit();
		img=NULL;
	}
	FreeLibrary(hmod);
	hmod=NULL;
	return NOERROR;
}

STDMETHODIMP Filter::SetExtEff(int itExtEff)
{
	iExtEff=itExtEff;
	return NOERROR;
}

STDMETHODIMP Filter::SetOptions(int itOption)
{
	iOption=itOption;
	return NOERROR;
}

STDMETHODIMP Filter::SetSmooth(int itOptionSmooth)
{
	iOptionSmooth=itOptionSmooth;
	return NOERROR;
}

CUnknown* WINAPI Filter::CreateInstance(LPUNKNOWN punk,HRESULT *phr)
{
	Filter *pObject= new Filter(NAME("Filter"),punk,phr);
	if(pObject==NULL)
	{
		*phr=E_OUTOFMEMORY;
	}
	return pObject;
}

HRESULT Filter::CheckInputType(const CMediaType*pmtin)
{
	if(pmtin->majortype!=MEDIATYPE_Video)
	{
		return S_FALSE;
	}
	else
	{
		if(pmtin->subtype==MEDIASUBTYPE_RGB24)
		{

			m_filter.SetResolution(cxImage,cyImage);

			return S_OK;
		}
		return S_FALSE;
	}
}

HRESULT Filter::Transform(IMediaSample*pSample)
{
	AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
	VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
	// Get the image properties from the BITMAPINFOHEADER
	cxImage = pvi->bmiHeader.biWidth;
	cyImage = pvi->bmiHeader.biHeight;

	BYTE *pData;                // Pointer to the actual image buffer
	
    pSample->GetPointer(&pData);

	m_filter.SetData(pData,cxImage,cyImage);
	//m_filter.SetDataPointer(pData);
	
	if(iOptionSmooth)
	{
		m_filter.SimpleSmooth();
	}

    m_filter.SelectFilter(iOption);

	if(iExtEff)
	{
		if(img)
		{
			img->Process((RGBTRIPLE*)pData,cxImage,cyImage);
		}
		
	}
    return NOERROR;
}

HRESULT Filter::NonDelegatingQueryInterface(REFIID riid,void**ppv)
{
	if(riid==IID_FilterInterface)
	{
		return GetInterface((IFilterInterface*)this,ppv);
	}
	else
	{
		return CTransInPlaceFilter::NonDelegatingQueryInterface(riid,ppv);
	}
}
STDMETHODIMP Filter::SelectConfigure()
{
	m_filter.SelectConfigFilter();
	return NOERROR;
}
/*void Filter::FreeMediaType(AM_MEDIA_TYPE*pmt)
{
	if (pmt->cbFormat != 0)
	{
		CoTaskMemFree((PVOID)pmt->pbFormat);
		pmt->cbFormat = 0;
		pmt->pbFormat = NULL;
	}
	if (pmt->pUnk != NULL)
	{
		// Unecessary because pUnk should not be used, but safest.
		pmt->pUnk->Release();
		pmt->pUnk = NULL;
	}
}
*/
 //RGB  ==> YIQ

			  //tr=(float)(0.299*prgb->rgbtRed+0.587*prgb->rgbtGreen+0.114*prgb->rgbtBlue);
			  //tg=(float)(0.596*prgb->rgbtRed-0.274*prgb->rgbtGreen+0.322*prgb->rgbtBlue);
			  //tb=(float)(0.212*prgb->rgbtRed-0.523*prgb->rgbtGreen+0.312*prgb->rgbtBlue);

			  //tr+=.9;

		 

			  //YIQ ==> RGB
			  
			  //prgb->rgbtRed=(BYTE)(-1.129*tr+3.306*tg-3.000*tb);
			  //prgb->rgbtGreen=(BYTE)(1.607*tr-0.934*tg+0.386*tb);
			  //prgb->rgbtBlue=(BYTE)(3.458*tr-3.817*tg+5.881*tb);

			 
			  //lum = (current[0] * 0.30) + (current[1] * 0.59) + (current[2] * 0.11);
			  /*tr=prgb->rgbtRed*0.30+prgb->rgbtGreen*0.59+prgb->rgbtBlue*0.11;

			  prgb->rgbtRed=prgb->rgbtRed*tr/255;
			  prgb->rgbtGreen=prgb->rgbtGreen*tr/255;
			  prgb->rgbtBlue=prgb->rgbtBlue*tr/255;
			  */

			   /** Third : home-made...*/
			   /*y = 0.333 * r + 0.333 * g + 0.333 * b;
			   u = r - y;
			   v = g - y;
			   r = y + u;
			   g = y + v;
			   b = y -u -v;
			   */

			 /* tr=0.333*prgb->rgbtRed+0.333*prgb->rgbtGreen+0.333*prgb->rgbtBlue;
			  tg=prgb->rgbtRed-tr;
			  tb=prgb->rgbtGreen-tr;

			  tr+=50;
			  
			  prgb->rgbtRed=tr+tg;
			  prgb->rgbtGreen=tr+tb;
			  prgb->rgbtBlue=tr-tg-tb;
			  */

			  /*

			  pix.Red=prgb->rgbtRed;
			  pix.Green=prgb->rgbtGreen;
			  pix.Blue=prgb->rgbtBlue;

			  //pix.data=pix.data>>1;
			  //pix.Alpha=0;

			  prgb->rgbtRed=pix.Red;
			  prgb->rgbtGreen=pix.Green;
			  prgb->rgbtBlue=pix.Blue;
			  */
/* for(ix=0;ix<cxImage-1;ix++,prgb++)
			  {
				  //lum = (current[0] * 0.30) + (current[1] * 0.59) + (current[2] * 0.11);
				  tr=(BYTE)(prgb->rgbtRed *(float)0.30+prgb->rgbtGreen*(float)0.59+prgb->rgbtBlue*(float)0.11);
				  prgb->rgbtRed=(BYTE)(prgb->rgbtRed *tr)/256;
				  prgb->rgbtGreen=(BYTE)(prgb->rgbtGreen*tr)/256;
				  prgb->rgbtBlue=(BYTE)(prgb->rgbtBlue*tr)/256;
			  }*/


//	 This is for main vision scripts
	//		X=((double)iy/cyImage)*255.0;
	//		Y=((double)ix/cxImage)*255.0;
	//		R=((double)prgb->rgbtRed/255.0);
	//		G=((double)prgb->rgbtGreen/255.0);
	//		B=((double)prgb->rgbtBlue/255.0);






